/*********************************************/
#include "iic.h"

void (* SDA_IN)(void); 
void (* SDA_OUT)(void); 

void (*IIC_SCL_L)(void); 
void (* IIC_SCL_H)(void);  

void (*IIC_SDA_L)(void);  
void (* IIC_SDA_H)(void);  

uint8_t (*READ_SDA)(void); 
	   
/****************************************************/
void iic_sw(struct IIC *S)
{ 
    SDA_IN = S->SDA_IN; 
    SDA_OUT = S->SDA_OUT; 

    IIC_SCL_L = S->SCL_L; 
    IIC_SCL_H = S->SCL_H;  

    IIC_SDA_L = S->SDA_L;  
    IIC_SDA_H = S->SDA_H;  

    READ_SDA = S->READ_SDA; 
}
/****************************************************/
void iic_delay()
{
  uint16_t i;
  for(i = 0; i < 20; i++);  //10 = 700us, 15 = 1ms, 20 = 1.1ms 
}
/************************************************/
void iic_start(void) 
{
  	SDA_OUT();     
	IIC_SDA_H();	  	  
	IIC_SCL_H();
	iic_delay();
 	IIC_SDA_L(); 
	iic_delay();
	IIC_SCL_L();	         
}
/*********************************************/
void iic_stop(void) 
{
  SDA_OUT();//sda???
  IIC_SCL_L();
  IIC_SDA_L();//STOP:when CLK is high DATA change form low to high
  iic_delay();
  IIC_SCL_H(); 
  IIC_SDA_H();//??I2C??????
  iic_delay();				
}
/************************************************/
void iic_ack(void) 
{    
  IIC_SCL_L();
  SDA_OUT();
  IIC_SDA_L();
  iic_delay();
  IIC_SCL_H();
  iic_delay();
  IIC_SCL_L();
}
/***********************************************/
void iic_no_ack(void) 
{  
  IIC_SCL_L();
  SDA_OUT();
  IIC_SDA_H();
  iic_delay();
  IIC_SCL_H();
  iic_delay();
  IIC_SCL_L();
}
/*************************************************/
uint8_t iic_wait_ack(void) 
{  
  uint8_t err_time = 0;

  SDA_IN();        
  IIC_SDA_H();
  iic_delay();	   
  IIC_SCL_H();
  iic_delay();	 
  while(READ_SDA())
  {
    err_time++;
	if(err_time > 50)
	{
	  iic_stop();
	  return 1;
	}
	iic_delay();
  }
  IIC_SCL_L(); 	   
  return 0;  
}
/**********************************************/
void iic_write_byte(char data) 
{
  uint8_t i;   
  SDA_OUT(); 	    
  IIC_SCL_L();//??????????
  for(i = 0; i < 8; i++)
  {              
     if((data & 0x80) >> 7)
     {
        IIC_SDA_H();
     }
     else
     {
        IIC_SDA_L();
     }
    data <<= 1; 	  
		iic_delay();   
		IIC_SCL_H();
		iic_delay(); 
		IIC_SCL_L();	
		iic_delay();
  }	 
}
/*************************************************/
uint8_t iic_read_byte(uint8_t ack)
{				  
  uint8_t i,receive = 0;

  SDA_IN();
  for(i = 0; i < 8; i++ )
  {
    IIC_SCL_L(); 
    iic_delay();
    IIC_SCL_H();
    receive <<= 1;
    if(READ_SDA())
	{
	  receive++;
	}   
	iic_delay(); 
  }					 
  if (ack)
  {
    iic_ack(); //??ACK
  } 
  else
  {
    iic_no_ack();//??nACK
  }  
  return receive;
}
/*************************************************/
uint8_t iic_rw(uint8_t *data_buff, uint8_t byte_quantity, uint8_t reg_address, uint8_t slave_address, uint8_t control_byte)
{
  uint8_t error_flag = 1, j = 1, i = 0;

  while(j--)
  {
    /* ??? */
    iic_start();

    /* ??????(?)*/
    iic_write_byte(slave_address + WRITE);
	  iic_wait_ack();
  
    /* ???? */
    iic_write_byte(reg_address);
	  iic_wait_ack();

	  /* ??? */
    if(control_byte == 0)
    { 
	  for(i = 0; i < byte_quantity; i++)                  
      {
	    iic_write_byte(*data_buff);
    	iic_wait_ack();
		data_buff++;
      }
	  iic_stop();
	  if(error_flag == 1) 
	  {
	    error_flag = 0;
	  }
    }
    else
    {
      iic_start();

      /* ??????(?) */
      iic_write_byte(slave_address + READ);
	  iic_wait_ack();
      /* ??? */
      for(i = 0; i < byte_quantity - 1; i++) 
      {
	    *data_buff = iic_read_byte(1);
	    data_buff++;
	  }
	  *data_buff = iic_read_byte(0);      
      iic_stop();
	  error_flag = 0;
	}
  }
  return error_flag;
}  
/***************************END OF FILE**********************************************************************/
